package com.wordlearning.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wordlearning.app.entity.WordSet;
import com.wordlearning.app.entity.Word;
import com.wordlearning.app.repository.WordSetRepository;
import com.wordlearning.app.repository.WordRepository;
import com.wordlearning.app.service.WordSetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class WordSetServiceImpl implements WordSetService {

    private final WordSetRepository wordSetRepository;
    private final WordRepository wordRepository;

    @Autowired
    public WordSetServiceImpl(WordSetRepository wordSetRepository, WordRepository wordRepository) {
        this.wordSetRepository = wordSetRepository;
        this.wordRepository = wordRepository;
    }

    @Override
    @Transactional
    public WordSet createWordSet(WordSet wordSet) {
        if (wordSetRepository.existsByNameAndUserId(wordSet.getName(), wordSet.getUserId())) {
            throw new IllegalArgumentException("Word set already exists with name: " + wordSet.getName());
        }
        if (wordSet.getWords() == null) {
            wordSet.setWords(Collections.emptyList());
        }
        wordSetRepository.insert(wordSet);
        return wordSet;
    }

    @Override
    public List<WordSet> getAllWordSets() {
        return wordSetRepository.selectList(null);
    }

    @Override
    public List<WordSet> getWordSetsByUserId(Long userId) {
        return wordSetRepository.findByUserId(userId);
    }

    @Override
    public Optional<WordSet> getWordSetById(Long id) {
        return wordSetRepository.selectById(id);
    }

    @Override
    @Transactional
    public WordSet updateWordSet(Long id, WordSet wordSet) {
        WordSet existingWordSet = wordSetRepository.selectById(id)
                .orElseThrow(() -> new IllegalArgumentException("Word set not found with id: " + id));

        existingWordSet.setName(wordSet.getName());
        existingWordSet.setDescription(wordSet.getDescription());
        existingWordSet.setWords(wordSet.getWords());

        wordSetRepository.updateById(existingWordSet);
        return existingWordSet;
    }

    @Override
    @Transactional
    public void deleteWordSet(Long id) {
        wordSetRepository.selectById(id)
                .orElseThrow(() -> new IllegalArgumentException("Word set not found with id: " + id));
        wordSetRepository.deleteById(id);
    }

    @Override
    @Transactional
    public WordSet addWordToWordSet(Long wordSetId, Long wordId) {
        WordSet wordSet = wordSetRepository.selectById(wordSetId)
                .orElseThrow(() -> new IllegalArgumentException("Word set not found with id: " + wordSetId));
        Word word = wordRepository.selectById(wordId)
                .orElseThrow(() -> new IllegalArgumentException("Word not found with id: " + wordId));

        if (!wordSet.getWords().contains(word)) {
            wordSet.getWords().add(word);
            wordSetRepository.updateById(wordSet);
        }
        return wordSet;
    }

    @Override
    @Transactional
    public WordSet removeWordFromWordSet(Long wordSetId, Long wordId) {
        WordSet wordSet = wordSetRepository.selectById(wordSetId)
                .orElseThrow(() -> new IllegalArgumentException("Word set not found with id: " + wordSetId));
        Word word = wordRepository.selectById(wordId)
                .orElseThrow(() -> new IllegalArgumentException("Word not found with id: " + wordId));

        if (wordSet.getWords().contains(word)) {
            wordSet.getWords().remove(word);
            wordSetRepository.updateById(wordSet);
        }
        return wordSet;
    }

    @Override
    public List<Word> getWordsInWordSet(Long wordSetId) {
        WordSet wordSet = wordSetRepository.selectById(wordSetId)
                .orElseThrow(() -> new IllegalArgumentException("Word set not found with id: " + wordSetId));
        return wordSet.getWords();
    }
}